其他
windows64位分页机制分析-隐藏可执行内存方法
本文为看雪论坛优秀文章
看雪论坛作者ID:git_18973smallzhong
1
win7 64位 MiIsAddressValid 函数分析
printf("%llx", ~0x98000000000 + 1);
>>> fffff68000000000
2
win10 64位 MiIsAddressValid 函数分析
3
通过修改pde和pte属性隐藏可执行内存
DWORD addr;
scanf("%x", &addr);
__asm
{
jmp addr
}
#include "memory.h"
#include "shellcode.h"
ULONG getOsVersionNumber()
{
/*
Windows 10(20H2) 19042
Windows 10(2004) 19041
Windows 10(1909) 18363
Windows 10(1903) 18362
Windows 10(1809) 17763
Windows 10(1803) 17134
Windows 10(1709) 16299
Windows 10(1703) 15063
Windows 10(1607) 14393
Windows 10(1511) 10586
Windows 10 (1507) 10240
Windows 8.1(更新1) MajorVersion = 6 MinorVersion = 3 BuildNumber = 9600
Windows 8.1 MajorVersion = 6 MinorVersion = 3 BuildNumber = 9200
Windows 8 MajorVersion = 6 MinorVersion = 2 BuildNumber = 9200
*/
RTL_OSVERSIONINFOEXW version = {0};
NTSTATUS status = RtlGetVersion(&version);
if (!NT_SUCCESS(status))
{
return 0;
}
return version.dwBuildNumber;
}
ULONG64 getPte(ULONG64 VirtualAddress)
{
ULONG64 pteBase = getPteBase();
return ((VirtualAddress >> 9) & 0x7FFFFFFFF8) + pteBase;
}
ULONG64 getPde(ULONG64 VirtualAddress)
{
ULONG64 pteBase = getPteBase();
ULONG64 pte = getPte(VirtualAddress);
return ((pte >> 9) & 0x7FFFFFFFF8) + pteBase;
}
ULONG64 getPdpte(ULONG64 VirtualAddress)
{
ULONG64 pteBase = getPteBase();
ULONG64 pde = getPde(VirtualAddress);
return ((pde >> 9) & 0x7FFFFFFFF8) + pteBase;
}
ULONG64 getPml4e(ULONG64 VirtualAddress)
{
ULONG64 pteBase = getPteBase();
ULONG64 ppe = getPdpte(VirtualAddress);
return ((ppe >> 9) & 0x7FFFFFFFF8) + pteBase;
}
ULONG64 getPteBase()
{
static ULONG64 pte_base = NULL;
if (pte_base) return pte_base;
// 获取os版本
ULONG64 versionNumber = 0;
versionNumber = getOsVersionNumber();
KdPrintEx((77, 0, "系统版本%lld\r\n", versionNumber));
// win7或者1607以下
if (versionNumber == 7601 || versionNumber == 7600 || versionNumber < 14393)
{
pte_base = 0xFFFFF68000000000ull;
return pte_base;
}
else // win10 1607以上
{
//取PTE(第一种)
UNICODE_STRING unName = { 0 };
RtlInitUnicodeString(&unName, L"MmGetVirtualForPhysical");
PUCHAR func = (PUCHAR)MmGetSystemRoutineAddress(&unName);
pte_base = *(PULONG64)(func + 0x22);
return pte_base;
}
return pte_base;
}
PVOID AllocateMemory(HANDLE pid, ULONG64 size)
{
PEPROCESS Process = NULL;
NTSTATUS status = PsLookupProcessByProcessId(pid, &Process);
if (!NT_SUCCESS(status))
{
return NULL;
}
// 如果当前找到的进程已经退出
if (PsGetProcessExitStatus(Process) != STATUS_PENDING)
{
return NULL;
}
KAPC_STATE kapc_state = { 0 };
KeStackAttachProcess(Process, &kapc_state);
PVOID BaseAddress = NULL;
status = ZwAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress, 0, &size, MEM_COMMIT, PAGE_READWRITE);
if (!NT_SUCCESS(status))
{
return NULL;
}
//写入shellcode
RtlMoveMemory(BaseAddress, shellcode, sizeof(shellcode);
// 修改可执行
SetExecutePage(BaseAddress, size);
KeUnstackDetachProcess(&kapc_state);
return BaseAddress;
}
BOOLEAN SetExecutePage(ULONG64 VirtualAddress, ULONG size)
{
ULONG64 startAddress = VirtualAddress & (~0xFFF); // 起始地址
ULONG64 endAddress = (VirtualAddress + size) & (~0xFFF); // 结束地址
for (ULONG64 curAddress = startAddress; curAddress <= endAddress; curAddress += PAGE_SIZE)
{
PHardwarePte pde = getPde(curAddress);
KdPrintEx((77, 0, "修改之前pde = %llx ", *pde));
if (MmIsAddressValid(pde) && pde->valid == 1)
{
pde->no_execute = 0;
pde->write = 1;
}
PHardwarePte pte = getPte(curAddress);
KdPrintEx((77, 0, "pte = %llx\r\n", *pte));
if (MmIsAddressValid(pte) && pte->valid == 1)
{
pte->no_execute = 0;
pte->write = 1;
}
KdPrintEx((77, 0, "pde = %p pte = %p address = %p\r\n", pde, pte, curAddress));
KdPrintEx((77, 0, "修改之后pde = %llx pte = %llx\r\n", *pde, *pte));
}
return TRUE;
}
E N D
看雪ID:git_18973smallzhong
https://bbs.pediy.com/user-home-899076.htm
# 往期推荐
5.Chrom V8分析入门——Google CTF2018 justintime分析
点击“阅读原文”了解更多